UInt/SInt
Description
The UInt
/SInt
type corresponds to a vector of bits that can be used for signed/unsigned integer arithmetic.
Declaration
The syntax to declare an integer is as follows: (everything between [] is optional)
Syntax |
Description |
Return |
---|---|---|
UInt[()]
SInt[()]
|
Create an unsigned/signed integer, bits count is inferred |
UInt
SInt
|
UInt(x bits)
SInt(x bits)
|
Create an unsigned/signed integer with x bits |
UInt
SInt
|
U(value: Int[,x bits])
U(value: BigInt[,x bits])
S(value: Int[,x bits])
S(value: BigInt[,x bits])
|
Create an unsigned/signed integer assigned with ‘value’ |
UInt
SInt
|
U”[[size’]base]value”
S”[[size’]base]value”
|
Create an unsigned/signed integer assigned with ‘value’ (Base : ‘h’, ‘d’, ‘o’, ‘b’) |
UInt
SInt
|
Create an unsigned integer assigned with the value specified by elements |
UInt
SInt
|
val myUInt = UInt(8 bits)
myUInt := U(2,8 bits)
myUInt := U(2)
myUInt := U"0000_0101" // Base per default is binary => 5
myUInt := U"h1A" // Base could be x (base 16)
// h (base 16)
// d (base 10)
// o (base 8)
// b (base 2)
myUInt := U"8'h1A"
myUInt := 2 // You can use scala Int as literal value
val myBool := myUInt === U(7 -> true,(6 downto 0) -> false)
val myBool := myUInt === U(myUInt.range -> true)
// For assignement purposes, you can omit the U/S, which also alow the use of the [default -> ???] feature
myUInt := (default -> true) //Assign myUInt with "11111111"
myUInt := (myUInt.range -> true) //Assign myUInt with "11111111"
myUInt := (7 -> true, default -> false) //Assign myUInt with "10000000"
myUInt := ((4 downto 1) -> true, default -> false) //Assign myUInt with "00011110"
Operators
The following operators are available for the UInt
and SInt
type
Logic
Operator |
Description |
Return type |
---|---|---|
x ^ y |
Logical XOR |
Bool |
~x |
Bitwise NOT |
T(w(x) bits) |
x & y |
Bitwise AND |
T(max(w(xy) bits) |
x | y |
Bitwise OR |
T(max(w(xy) bits) |
x ^ y |
Bitwise XOR |
T(max(w(xy) bits) |
x.xorR |
XOR all bits of x |
Bool |
x.orR |
OR all bits of x |
Bool |
x.andR |
AND all bits of x |
Bool |
x >> y |
Arithmetic shift right, y : Int |
T(w(x) - y bits) |
x >> y |
Arithmetic shift right, y : UInt |
T(w(x) bits) |
x << y |
Arithmetic shift left, y : Int |
T(w(x) + y bits) |
x << y |
Arithmetic shift left, y : UInt |
T(w(x) + max(y) bits) |
x |>> y |
Logical shift right, y : Int/UInt |
T(w(x) bits) |
x |<< y |
Logical shift left, y : Int/UInt |
T(w(x) bits) |
x.rotateLeft(y) |
Logical left rotation, y : UInt/Int |
T(w(x) bits) |
x.rotateRight(y) |
Logical right rotation, y : UInt/Int |
T(w(x) bits) |
x.clearAll[()] |
Clear all bits |
|
x.setAll[()] |
Set all bits |
|
x.setAllTo(value : Boolean) |
Set all bits to the given Boolean value |
|
x.setAllTo(value : Bool) |
Set all bits to the given Bool value |
// Bitwise operator
val a, b, c = SInt(32 bits)
c := ~(a & b) // Inverse(a AND b)
val all_1 = a.andR // Check that all bits are equal to 1
// Logical shift
val uint_10bits = uint_8bits << 2 // shift left (resulting in 10 bits)
val shift_8bits = uint_8bits |<< 2 // shift left (resulting in 8 bits)
// Logical rotation
val myBits = uint_8bits.rotateLeft(3) // left bit rotation
// Set/clear
val a = B"8'x42"
when(cond){
a.setAll() // set all bits to True when cond is True
}
Arithmetic
Operator |
Description |
Return |
---|---|---|
x + y |
Addition |
T(max(w(x), w(y)),bits) |
x +^ y |
Addition with carray |
T(max(w(x), w(y) + 1),bits) |
x +| y |
addition by sat carray bit |
T(max(w(x), w(y)),bits) |
x - y |
Subtraction |
T(max(w(x), w(y)),bits) |
x - y |
Subtraction with carray |
T(max(w(x), w(y) + 1), bits) |
x -| y |
Subtraction by sat carray bit |
T(max(w(x), w(y)),bits) |
x * y |
Multiplication |
T(w(x) + w(y)), bits) |
x / y |
Division |
T(w(x),bits) |
x % y |
Modulo |
T(w(x),bits) |
// Addition
val res = mySInt_1 + mySInt_2
Comparison
Operator |
Description |
Return type |
---|---|---|
x === y |
Equality |
Bool |
x =/= y |
Inequality |
Bool |
x > y |
Greater than |
Bool |
x >= y |
Greater than or equal |
Bool |
x < y |
Less than |
Bool |
x <= y |
Less than or equal |
Bool |
// Comparaison between two SInt
myBool := mySInt_1 > mySInt_2
// Comparaison between a UInt and a literal
myBool := myUInt_8bits >= U(3, 8 bits)
when(myUInt_8bits === 3){
}
Type cast
Operator |
Description |
Return |
---|---|---|
x.asBits |
Binary cast to Bits |
Bits(w(x),bits) |
x.asUInt |
Binary cast to UInt |
UInt(w(x),bits) |
x.asSInt |
Binary cast to SInt |
SInt(w(x),bits) |
x.asBools |
Cast into a array of Bool |
Vec(Bool, w(x)) |
S(x: T) |
Cast a Data into a SInt |
SInt(w(x),bits) |
U(x: T) |
Cast a Data into an UInt |
UInt(w(x),bits) |
x.intoSInt |
convert to SInt expand signbit |
SInt(w(x) + 1, bits) |
To cast a Bool, a Bits or a SInt into a UInt, you can use U(something)
. To cast things into a SInt, you can use S(something)
// cast a SInt to Bits
val myBits = mySInt.asBits
// create a Vector of bool
val myVec = myUInt.asBools
// Cast a Bits to SInt
val mySInt = S(myBits)
Bit extraction
Operator |
Description |
Return |
---|---|---|
x(y) |
Readbit, y : Int/UInt |
Bool |
x(offset, width) |
Read bitfield, offset: UInt, width: Int |
T(width bits) |
x(range) |
Read a range of bits. Ex : myBits(4 downto 2) |
T(range bits) |
x(y) := z |
Assign bits, y : Int/UInt |
Bool |
x(offset, width) := z |
Assign bitfield, offset: UInt, width: Int |
T(width bits) |
x(range) := z |
Assign a range of bit. Ex : myBits(4 downto 2) := U”010” |
T(range bits) |
// get the bit at index 4
val myBool = myUInt(4)
// assign bit 1 to True
mySInt(1) := True
// Range
val myUInt_8bits = myUInt_16bits(7 downto 0)
val myUInt_7bits = myUInt_16bits(0 to 6)
val myUInt_6bits = myUInt_16Bits(0 until 6)
mySInt_8bits(3 downto 0) := mySInt_4bits
Misc
Operator |
Description |
Return |
---|---|---|
x.getWidth |
Return bitcount |
Int |
x.msb |
Return the most significant bit |
Bool |
x.lsb |
Return the least significant bit |
Bool |
x.range |
Return the range (x.high downto 0) |
Range |
x.high |
Return the upper bound of the type x |
Int |
x ## y |
Concatenate, x->high, y->low |
Bits(w(x) + w(y) bits) |
x @@ y |
Concatenate x:T with y:Bool/SInt/UInt |
T(w(x) + w(y) bits) |
x.subdivideIn(y slices) |
Subdivide x into y slices, y: Int |
Vec(T, y) |
x.subdivideIn(y bits) |
Subdivide x into multiple slices of y bits, y: Int |
Vec(T, w(x)/y) |
x.resize(y) |
Return a resized copy of x, if enlarged, it is filled with zero
for UInt or filled with the sign for SInt, y: Int
|
T(y bits) |
x.resized |
Return a version of x which is allowed to be automatically
resized where needed
|
T(w(x) bits) |
myUInt.twoComplement(en: Bool) |
Use the two’s complement to transform an UInt into an SInt |
SInt(w(myUInt) + 1, bits) |
mySInt.abs |
Return the absolute value of the UInt value |
UInt(w(mySInt), bits) |
mySInt.abs(en: Bool) |
Return the absolute value of the UInt value when en is True |
UInt(w(mySInt), bits) |
mySInt.sign |
Return most significant bit |
Bool |
x.expand |
Return x with 1 bit expand |
T(w(x)+1 bit) |
mySInt.absWithSym |
Return the absolute value of the UInt value with symmetric, shrink 1 bit |
UInt(w(mySInt) - 1, bits) |
myBool := mySInt.lsb // equivalent to mySInt(0)
// Concatenation
val mySInt = mySInt_1 @@ mySInt_1 @@ myBool
val myBits = mySInt_1 ## mySInt_1 ## myBool
// Subdivide
val sel = UInt(2 bits)
val mySIntWord = mySInt_128bits.subdivideIn(32 bits)(sel)
// sel = 0 => mySIntWord = mySInt_128bits(127 downto 96)
// sel = 1 => mySIntWord = mySInt_128bits( 95 downto 64)
// sel = 2 => mySIntWord = mySInt_128bits( 63 downto 32)
// sel = 3 => mySIntWord = mySInt_128bits( 31 downto 0)
// if you want to access in a reverse order you can do
val myVector = mySInt_128bits.subdivideIn(32 bits).reverse
val mySIntWord = myVector(sel)
// Resize
myUInt_32bits := U"32'x112233344"
myUInt_8bits := myUInt_32bits.resized // automatic resize (myUInt_8bits = 0x44)
myUInt_8bits := myUInt_32bits.resize(8) // resize to 8 bits (myUInt_8bits = 0x44)
// Two's complement
mySInt := myUInt.twoComplement(myBool)
// Absolute value
mySInt_abs := mySInt.abs
fixPoint operation
- For fixed-point, we can divide it into two parts.
LowerBit Operation(round methods)
HighBit Operation(saturation operations)
Lower Bit operation
About Rounding: https://en.wikipedia.org/wiki/Rounding
SpinalHDL-Name |
Wikipedia-Name |
API |
Matmatic-Alogrithm |
return(align=false) |
Supported |
---|---|---|---|---|---|
FLOOR |
RoundDown |
floor |
floor(x) |
w(x)-n bits |
Yes |
FLOORTOZERO |
RoundToZero |
floorToZero |
sign*floor(abs(x)) |
w(x)-n bits |
Yes |
CEIL |
RoundUp |
ceil |
ceil(x) |
w(x)-n+1 bits |
Yes |
CEILTOINF |
RoundToInf |
ceilToInf |
sign*ceil(abs(x)) |
w(x)-n+1 bits |
Yes |
ROUNDUP |
RoundHalfUp |
roundUp |
floor(x+0.5) |
w(x)-n+1 bits |
Yes |
ROUNDDOWN |
RoundHalfDown |
roundDown |
ceil(x-0.5) |
w(x)-n+1 bits |
Yes |
ROUNDTOZERO |
RoundHalfToZero |
roundToZero |
sign*ceil(abs(x)-0.5) |
w(x)-n+1 bits |
Yes |
ROUNDTOINF |
RoundHalfToInf |
roundToInf |
sign*floor(abs(x)+0.5) |
w(x)-n+1 bits |
Yes |
ROUNDTOEVEN |
RoundHalfToEven |
roundToEven |
No |
||
ROUNDTOODD |
RoundHalfToOdd |
roundToOdd |
No |
Note
You can find ROUNDUP, ROUNDDOWN, ROUNDTOZERO, ROUNDTOINF, ROUNDTOEVEN, ROUNTOODD are very close, ROUNDTOINF is most common. the api of round in different Programing-language may different.
Programing-language |
default-RoundType |
Example |
comments |
---|---|---|---|
Matlab |
ROUNDTOINF |
round(1.5)=2,round(2.5)=3;round(-1.5)=-2,round(-2.5)=-3 |
round to ±Infinity |
python2 |
ROUNDTOINF |
round(1.5)=2,round(2.5)=3;round(-1.5)=-2,round(-2.5)=-3 |
round to ±Infinity |
python3 |
ROUNDTOEVEN |
round(1.5)=round(2.5)=2; round(-1.5)=round(-2.5)=-2 |
close to Even |
Scala.math |
ROUNDTOUP |
round(1.5)=2,round(2.5)=3;round(-1.5)=-1,round(-2.5)=-2 |
always to +Infinity |
SpinalHDL |
ROUNDTOINF |
round(1.5)=2,round(2.5)=3;round(-1.5)=-2,round(-2.5)=-3 |
round to ±Infinity |
Note
In SpinalHDL ROUNDTOINF is the default RoundType (round = roundToInf)
val A = SInt(16 bit)
val B = A.roundToInf(6 bits) //default 'align = false' with carry, got 11 bit
val B = A.roundToInf(6 bits, align = true) // sat 1 carry bit, got 10 bit
val B = A.floor(6 bits) //return 10 bit
val B = A.floorToZero(6 bits) //return 10 bit
val B = A.ceil(6 bits) //ceil with carry so return 11 bit
val B = A.ceil(6 bits, align =true) //ceil with carry then sat 1 bit return 10 bit
val B = A.ceilToInf(6 bits)
val B = A.roundUp(6 bits)
val B = A.roundDown(6 bits)
val B = A.roundToInf(6 bits)
val B = A.roundToZero(6 bits)
val B = A.round(6 bits) //spinalHDL use roundToInf as default round
val B0 = A.roundToInf(6 bits, align=true) ---+
|--> equal
val B1 = A.roundToInf(6 bits, align=false).sat(1) ---+
Note
round Api
API |
UInt/SInt |
description |
Return(align=false) |
Return(align=true) |
---|---|---|---|---|
floor |
Both |
w(x)-n bits |
w(x)-n bits |
|
floorToZero |
SInt |
equal to floor in UInt |
w(x)-n bits |
w(x)-n bits |
ceil |
Both |
w(x)-n+1 bits |
w(x)-n bits |
|
ceilToInf |
SInt |
equal to ceil in UInt |
w(x)-n+1 bits |
w(x)-n bits |
roundUp |
Both |
simple for HW |
w(x)-n+1 bits |
w(x)-n bits |
roundDown |
Both |
w(x)-n+1 bits |
w(x)-n bits |
|
roundToInf |
SInt |
most Common |
w(x)-n+1 bits |
w(x)-n bits |
roundToZero |
SInt |
equal to roundDown in UInt |
w(x)-n+1 bits |
w(x)-n bits |
round |
Both |
SpinalHDL chose roundToInf |
w(x)-n+1 bits |
w(x)-n bits |
Note
High Bit operation
function |
Operation |
Postive-Op |
Negtive-Op |
supported |
---|---|---|---|---|
sat |
Saturation |
when(Top[w-1,w-n].orR) set maxValue |
When(Top[w-1,w-n].andR) set minValue |
Yes |
trim |
Discard |
N/A |
N/A |
Yes |
symmetry |
Symmetric |
N/A |
minValue = -maxValue |
Yes |
Symmetric is only valid for SInt.
val A = SInt(8 bit)
val B = A.sat(3 bits) //return 5 bits with saturated highest 3 bits
val B = A.sat(3) //equal to sat(3 bits)
val B = A.trim(3 bits) //return 5 bits with discard hightest 3 bits
val B = A.trim(3 bits) //return 5 bits with discard hightest 3 bits
val C = A.symmetry //return 8 bits and symmetry as (-128~127 to -127~127)
val C = A.sat(3).symmetry //return 5 bits and symmetry as (-16~15 to -15~15)
fixTo function
two way are provided in UInt/SInt do fixpoint:
fixTo is strongly recommended in your RTL work, you don’t need handle carry bit align and bit width calculate manually like Way1.
Factory Fix function with Auto Saturation
fuction |
description |
Return |
---|---|---|
fixTo(section,roundType,symmetric) |
Factory FixFunction |
section.size bits |
val A = SInt(16 bit)
val B = A.fixTo(10 downto 3) //default RoundType.ROUNDTOINF, sym = false
val B = A.fixTo( 8 downto 0, RoundType.ROUNDUP)
val B = A.fixTo( 9 downto 3, RoundType.CEIL, sym = false)
val B = A.fixTo(16 downto 1, RoundType.ROUNDTOINF, sym = true )
val B = A.fixTo(10 downto 3, RoundType.FLOOR) //floor 3 bit, sat 5 bit @ highest
val B = A.fixTo(20 downto 3, RoundType.FLOOR) //floor 3 bit, expand 2 bit @ highest